import 'dart:math';
import 'package:flutter/material.dart';

class JoystickController extends StatefulWidget {
  const JoystickController({Key? key}) : super(key: key);

  @override
  State<JoystickController> createState() => _JoystickControllerState();
}

class _JoystickControllerState extends State<JoystickController>
    with SingleTickerProviderStateMixin {
  double bigRadius = 120; // 大圆半径
  double smallRadius = 40; // 摇杆半径
  Offset joystickPos = Offset.zero; // 摇杆相对于中心的偏移
  late AnimationController _resetController;
  late Animation<Offset> _resetAnimation;
  int activeDirection = -1; // 当前方向（0-7），-1表示无方向

  @override
  void initState() {
    super.initState();
    _resetController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 200),
    );
    _resetController.addListener(() {
      setState(() {
        joystickPos = _resetAnimation.value;
        if (joystickPos == Offset.zero) {
          activeDirection = -1;
        }
      });
    });
  }

  @override
  void dispose() {
    _resetController.dispose();
    super.dispose();
  }

  void _onPanUpdate(DragUpdateDetails details) {
    final local = details.localPosition;
    final center = Offset(bigRadius, bigRadius);

    // 当前手指相对于中心的偏移
    Offset offset = local - center;

    // 限制在大圆范围内
    if (offset.distance > bigRadius - smallRadius) {
      final angle = atan2(offset.dy, offset.dx);
      offset = Offset(
        cos(angle) * (bigRadius - smallRadius),
        sin(angle) * (bigRadius - smallRadius),
      );
    }

    // 计算角度（0 - 360°）
    double angle = atan2(offset.dy, offset.dx) * 180 / pi;
    if (angle < 0) angle += 360;

    // 根据角度计算方向：每 45° 一个方向
    int direction = (angle / 45).floor() % 8;

    setState(() {
      joystickPos = offset;
      activeDirection = direction;
    });
  }

  void _onPanEnd(DragEndDetails details) {
    _resetAnimation =
        Tween<Offset>(begin: joystickPos, end: Offset.zero).animate(
          CurvedAnimation(parent: _resetController, curve: Curves.easeOut),
        );
    _resetController.forward(from: 0);
    setState(() {
      activeDirection = -1; // 松开后清空方向
    });
  }

  @override
  Widget build(BuildContext context) {
    final size = bigRadius * 2;

    return GestureDetector(
      onPanUpdate: _onPanUpdate,
      onPanEnd: _onPanEnd,
      child: SizedBox(
        width: size,
        height: size,
        child: Stack(
          alignment: Alignment.center,
          children: [
            // 大圆背景
            CustomPaint(
              size: Size(size, size),
              painter: _EightDirectionPainter(
                radius: bigRadius,
                activeDirection: activeDirection,
              ),
            ),

            // 小圆摇杆
            Positioned(
              left: bigRadius + joystickPos.dx - smallRadius,
              top: bigRadius + joystickPos.dy - smallRadius,
              child: Container(
                width: smallRadius * 2,
                height: smallRadius * 2,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: Colors.blueAccent,
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black26,
                      blurRadius: 8,
                      offset: Offset(2, 2),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/// 八方向扇形高亮/置灰 Painter
class _EightDirectionPainter extends CustomPainter {
  final double radius;
  final int activeDirection;

  _EightDirectionPainter({
    required this.radius,
    required this.activeDirection,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(radius, radius);
    final rect = Rect.fromCircle(center: center, radius: radius);
    final paint = Paint()..style = PaintingStyle.fill;

    // 每个扇形角度 45°
    for (int i = 0; i < 8; i++) {
      // 当前扇区角度起点
      double startAngle = -pi / 8 + i * pi / 4; // -22.5° 起始，居中显示
      paint.color = (i == activeDirection)
          ? Colors.grey.shade400
          : Colors.blue.shade300;
      canvas.drawArc(rect, startAngle, pi / 4, true, paint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
